package com.ruoyi.erp.controller;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.github.pagehelper.util.StringUtil;
import com.ruoyi.common.exception.job.TaskException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.erp.domain.*;
import com.ruoyi.erp.service.*;
import com.ruoyi.erp.service.impl.GlAccvouchServiceImpl;
import com.ruoyi.erp.service.impl.LedyFeeCheckinServiceImpl;
import com.ruoyi.erp.service.impl.TaskServiceImpl;
import com.ruoyi.quartz.domain.SysJob;
import com.ruoyi.quartz.service.ISysJobService;
import com.ruoyi.quartz.service.impl.SysJobServiceImpl;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.quartz.SchedulerException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
import org.springframework.web.multipart.MultipartFile;

/**
 * 收费管理Controller
 *
 * @author ztj
 * @date 2023-04-04
 */
@RestController
@RequestMapping("/erp/checkin")
public class LedyFeeCheckinController extends BaseController {
    @Autowired
    private ILedyFeeCheckinService ledyFeeCheckinService;
    @Autowired
    private IGlAccvouchService glAccvouchService;
    @Autowired
    private ILedyBacFeeConfigService configService;
    @Autowired
    private ICustomerService customerService;
    @Autowired
    private IGlCashtableService cashtableService;
    @Autowired
    private ISysJobService jobService;

    @Log(title = "凭证生成", businessType = BusinessType.IMPORT)
    @GetMapping("/sync/{ids}/{type}")
    public AjaxResult faSync(@PathVariable Long[] ids, @PathVariable String type, LedyFeeCheckin ledyFeeCheckin) {

        List<LedyFeeCheckin> checkins = ledyFeeCheckinService.selectLedyFeeCheckinByIds(ids);
        GlAccvouch accvouch = new GlAccvouch();
        GlAccvouch accvouchQuery = new GlAccvouch();
        List<LedyBacFeeConfig> confList = initAccvouch(ledyFeeCheckin.getDbillDate(), "feeCheckIn", glAccvouchService, configService, type, accvouch, accvouchQuery);
        final int[] i = {0};
//        if (ledyFeeCheckin.getIperiod() != null && ledyFeeCheckin.getIperiod() > 1) {
//
//            int iyear = Integer.parseInt(accvouch.getiYear());
//            int imonth = Integer.parseInt(accvouch.getIperiod());
//            logger.info("imonth" + imonth + iyear);
//            for (int j = 0; j < ledyFeeCheckin.getIperiod(); j++) {
//                logger.info("111" + j);
//                SysJob job = new SysJob();
//                job.setJobName(DateUtil.format(accvouch.getDbillDate(), "yyyy-MM-dd") + "~第" + (j + 1) + "期");
//                job.setJobGroup("收费TaskGroup");
//
//                if (imonth > 12) {
//                    imonth = 1;
//                    iyear++;
//                }
//
//                job.setCronExpression("0 0 0 " + accvouch.getDbillDate().getDate() + " " + imonth + " ? " + iyear);
//                job.setInvokeTarget("taskService.executeTaskWithParams('" + Arrays.stream(ids)
//                        .map(String::valueOf)
//                        .collect(Collectors.joining(",")) + "','" + type + "','" +
//                        iyear + "-" + imonth + "-" + accvouch.getDbillDate().getDate() + "'," + ledyFeeCheckin.getIperiod() + ")");
//                imonth++;
//
//                job.setMisfirePolicy("1");
//                job.setStatus("0");
//                job.setConcurrent("1");
//                job.setRemark("收费" + "第" + (j + 1) + "期");
//                try {
//
//                    jobService.insertJob(job);
//                } catch (SchedulerException e) {
//                    throw new RuntimeException(e);
//                } catch (TaskException e) {
//                    throw new RuntimeException(e);
//                }
//            }
//            checkins.forEach(item -> {
//                item.setIflag(1);
//                ledyFeeCheckinService.updateLedyFeeCheckin(item);
//            });
//            return toAjax(1);
//        }
        checkins.forEach(item -> {

            insertUser(i, glAccvouchService, customerService, type, accvouch, accvouchQuery, item.getAcceptNumber(), item.getPayers());
            String cusId = accvouch.getCcusId();
            confList.forEach(conf -> {
                i[0]++;
                if (!conf.getAuxiliaryTerm().contains("ccusId")) {
                    accvouch.setCcusId(null);
                } else {
                    accvouch.setCcusId(cusId);
                }
                accvouch.setInid(Long.parseLong(i[0] + ""));
                accvouch.setCcode(conf.getCcode());
                accvouch.setMd("0");
                accvouch.setMc("0");
                if (conf.getRecordCate().equals("借")) {
                    accvouch.setMd(item.getAmount().toString());
//                        try {
//                            accvouch.setMd(item.getClass().getMethod(conf.getAmount(), BigDecimal.class).invoke());
//                        } catch (NoSuchMethodException e) {
//                            e.printStackTrace();
//                        }
                } else {
                    if (conf.getAmount().equals("bacFee"))
                        accvouch.setMc(item.getBacFee().toString());
                    else
                        accvouch.setMc(item.getArbitratorFee().toString());
                }
                if (new BigDecimal(accvouch.getMc()).compareTo(new BigDecimal(0)) <= 0 && new BigDecimal(accvouch.getMd()).compareTo(new BigDecimal(0)) <= 0) {
                    i[0]--;
                    return;
                }
                accvouch.setCcodeEqual(confList.stream().map(s -> {
                    if (!s.getCcode().equals(conf.getCcode()) && !s.getRecordCate().equals(conf.getRecordCate())) {
                        if (s.getRecordCate().equals("借")) {
                            if (item.getAmount().compareTo(new BigDecimal(0)) <= 0) {
                                return null;
                            }
                        } else {
                            if (s.getAmount().equals("bacFee")) {
                                if (item.getBacFee().compareTo(new BigDecimal(0)) <= 0) {
                                    return null;
                                }
                            } else {
                                if (item.getArbitratorFee().compareTo(new BigDecimal(0)) <= 0) {
                                    return null;
                                }
                            }
                        }
                        return s.getCcode();
                    } else return null;
                }).distinct().collect(Collectors.joining(",")).replaceAll("null,", "").replace(",null", ""));
                accvouch.setCcodeexchEqual(accvouch.getCcodeEqual());
                accvouch.setCdigest("收费" + item.getAcceptNumber() + item.getPayers());
                accvouch.setCdigest(StringUtils.substring(accvouch.getCdigest(), 0, 110));

                glAccvouchService.insertGlAccvouch(accvouch);

                if (StringUtil.isNotEmpty(conf.getCashDesc())) {
                    GlCashtable castable = new GlCashtable();
                    BeanUtil.copyProperties(accvouch, castable);
                    castable.setcCashItem(conf.getCashDesc());
                    cashtableService.insertGlCashtable(castable);
                }
            });
            item.setiNoId(accvouch.getInoId().toString());
            item.setIflag(1);
            item.setDbillDate(accvouch.getDbillDate());
            ledyFeeCheckinService.updateLedyFeeCheckin(item);
        });

        return toAjax(1);
    }

    public static void faSync(Long[] ids, String type, String dbillDate, Integer iperiod, IGlAccvouchService glAccvouchService, ILedyFeeCheckinService ledyFeeCheckinService, ILedyBacFeeConfigService configService,ICustomerService customerService, IGlCashtableService cashtableService) {

        List<LedyFeeCheckin> checkins = ledyFeeCheckinService.selectLedyFeeCheckinByIds(ids);
        GlAccvouch accvouch = new GlAccvouch();
        GlAccvouch accvouchQuery = new GlAccvouch();
        List<LedyBacFeeConfig> confList = initAccvouch(DateUtils.parseDate(dbillDate), "feeCheckIn", glAccvouchService, configService, type, accvouch, accvouchQuery);
        final int[] i = {0};
        checkins.forEach(item -> {

            insertUser(i, glAccvouchService, customerService, type, accvouch, accvouchQuery, item.getAcceptNumber(), item.getPayers());
            String cusId = accvouch.getCcusId();
            confList.forEach(conf -> {
                i[0]++;
                if (!conf.getAuxiliaryTerm().contains("ccusId")) {
                    accvouch.setCcusId(null);
                } else {
                    accvouch.setCcusId(cusId);
                }
                accvouch.setInid(Long.parseLong(i[0] + ""));
                accvouch.setCcode(conf.getCcode());
                accvouch.setMd("0");
                accvouch.setMc("0");

                if (conf.getRecordCate().equals("借")) {
                    accvouch.setMd(item.getAmount().toString());
//                        try {
//                            accvouch.setMd(item.getClass().getMethod(conf.getAmount(), BigDecimal.class).invoke());
//                        } catch (NoSuchMethodException e) {
//                            e.printStackTrace();
//                        }
                } else {
                    if (conf.getAmount().equals("bacFee"))
                        accvouch.setMc(item.getBacFee().toString());
                    else
                        accvouch.setMc(item.getArbitratorFee().toString());
                }
                if (new BigDecimal(accvouch.getMc()).compareTo(new BigDecimal(0)) <= 0 && new BigDecimal(accvouch.getMd()).compareTo(new BigDecimal(0)) <= 0) {
                    i[0]--;
                    return;
                }
                if (new BigDecimal(accvouch.getMc().trim()).compareTo(new BigDecimal(0)) > 0) {
                    BigDecimal mc = new BigDecimal(accvouch.getMc()).divide(new BigDecimal(iperiod), 2, RoundingMode.HALF_UP);
                    accvouch.setMc(mc.toString());
                } else if (new BigDecimal(accvouch.getMd().trim()).compareTo(new BigDecimal(0)) > 0) {
                    BigDecimal md = new BigDecimal(accvouch.getMd()).divide(new BigDecimal(iperiod), 2, RoundingMode.HALF_UP);
                    accvouch.setMd(md.toString());
                }
                accvouch.setCcodeEqual(confList.stream().map(s -> {
                    if (!s.getCcode().equals(conf.getCcode()) && !s.getRecordCate().equals(conf.getRecordCate())) {
                        if (s.getRecordCate().equals("借")) {
                            if (item.getAmount().compareTo(new BigDecimal(0)) <= 0) {
                                return null;
                            }
                        } else {
                            if (s.getAmount().equals("bacFee")) {
                                if (item.getBacFee().compareTo(new BigDecimal(0)) <= 0) {
                                    return null;
                                }
                            } else {
                                if (item.getArbitratorFee().compareTo(new BigDecimal(0)) <= 0) {
                                    return null;
                                }
                            }
                        }
                        return s.getCcode();
                    } else return null;
                }).distinct().collect(Collectors.joining(",")).replaceAll("null,", "").replace(",null", ""));
                accvouch.setCcodeexchEqual(accvouch.getCcodeEqual());
                accvouch.setCdigest("收费" + item.getAcceptNumber() + item.getPayers());
                accvouch.setCdigest(StringUtils.substring(accvouch.getCdigest(), 0, 110));

                glAccvouchService.insertGlAccvouch(accvouch);

                if (StringUtil.isNotEmpty(conf.getCashDesc())) {
                    GlCashtable castable = new GlCashtable();
                    BeanUtil.copyProperties(accvouch, castable);
                    castable.setcCashItem(conf.getCashDesc());
                    cashtableService.insertGlCashtable(castable);
                }
            });
            item.setiNoId(accvouch.getInoId().toString());
            item.setIflag(1);
            item.setDbillDate(accvouch.getDbillDate());
            ledyFeeCheckinService.updateLedyFeeCheckin(item);
        });
    }

    static void insertUser(int[] i, IGlAccvouchService glAccvouchService, ICustomerService customerService, String type, GlAccvouch accvouch, GlAccvouch accvouchQuery, String acceptNumber, String payers) {
        if (!type.equals("1")) {
            GlAccvouch accvouchQueryReturn = glAccvouchService.selectGlAccvouchMaxId(accvouchQuery);
            if (accvouchQueryReturn == null || accvouchQueryReturn.getInoId() == null) {
                accvouch.setInoId(1);
            } else
                accvouch.setInoId(accvouchQueryReturn.getInoId() + 1);//当前年月最大编号
            i[0] = 0;
        }
        accvouch.setCdigest(StringUtils.substring(acceptNumber + payers, 0, 55));
        Customer customer = new Customer();
        customer.setcCusAbbName(accvouch.getCdigest());
        List<Customer> customers = customerService.selectCustomerList(customer);
        if (customers.size() == 0) {
            customer.setcCusCode(DateUtil.year(new Date()) + StringUtils.randomNumber(8));
            customer.setcCusName(StringUtils.substring(payers, 0, 55));
            customer.setcCCCode("00");
//            customer.setcCCCode("01");
            customer.setcCusMngTypeCode("999");
            customer.setCcusexchName("人民币");
//                        customer.setdCusDevDate(DateUtil.formatDate(new Date()));
            customerService.insertCustomer(customer);
            accvouch.setCcusId(customer.getcCusCode());
        } else {
            accvouch.setCcusId(customers.get(0).getcCusCode());//客户编码取erp
        }
    }

    static List<LedyBacFeeConfig> initAccvouch(Date billDate, String recordSchema, IGlAccvouchService glAccvouchService, ILedyBacFeeConfigService configService, String type, GlAccvouch accvouch, GlAccvouch accvouchQuery) {
        accvouch.setCbill("张洋");
        accvouch.setCsign("记");
        accvouch.setIsignseq("1");
        accvouch.setCname("-");
        accvouch.setIdoc("-1");
        accvouch.setDbillDate(billDate != null ? billDate : DateUtil.parse(DateUtil.today()));
        LedyBacFeeConfig config = new LedyBacFeeConfig();
        config.setStatus("Y");
        config.setRecordSchema(recordSchema);
        List<LedyBacFeeConfig> confList = configService.selectLedyBacFeeConfigList(config);

        accvouch.setiYear(DateUtil.year(accvouch.getDbillDate()) + "");
        accvouch.setIperiod((DateUtil.month(accvouch.getDbillDate()) + 1) + "");
        accvouch.setiYPeriod(DateUtil.format(accvouch.getDbillDate(), "yyyyMM"));
        accvouchQuery.setiYPeriod(DateUtil.format(accvouch.getDbillDate(), "yyyyMM"));
        if (type.equals("1")) {
            GlAccvouch accvouchQueryReturn = glAccvouchService.selectGlAccvouchMaxId(accvouchQuery);
            if (accvouchQueryReturn == null || accvouchQueryReturn.getInoId() == null) {
                accvouch.setInoId(1);
            } else
                accvouch.setInoId(accvouchQueryReturn.getInoId() + 1);//当前年月最大编号
        }
        return confList;
    }

    /**
     * 查询收费管理列表
     */
    @PreAuthorize("@ss.hasPermi('erp:checkin:list')")
    @GetMapping("/list")
    public TableDataInfo list(LedyFeeCheckin ledyFeeCheckin) {
        startPage();
        List<LedyFeeCheckin> list = ledyFeeCheckinService.selectLedyFeeCheckinList(ledyFeeCheckin);
        return getDataTable(list);
    }

    @Log(title = "Excel校对", businessType = BusinessType.IMPORT)
    @PreAuthorize("@ss.hasPermi('erp:checkin:export')")
    @PostMapping("/importData")
    public AjaxResult importData(HttpServletResponse response, MultipartFile file, boolean updateSupport) throws Exception {
        try {
            // 加载Excel文件
            XSSFWorkbook workbook = new XSSFWorkbook(file.getInputStream());
            XSSFSheet sheet = workbook.getSheetAt(0);

            // 遍历每一行，修改指定列的数据
            for (Row row : sheet) {
                Cell remark = row.getCell(18);
                if (remark.getStringCellValue().contains("收案编号:")) {
                    String number = remark.getStringCellValue().substring(5, 22);
                    LedyFeeCheckin ledyFeeCheckin = new LedyFeeCheckin();
                    ledyFeeCheckin.setAcceptNumber(number);
                    List<LedyFeeCheckin> list = ledyFeeCheckinService.selectLedyFeeCheckinList(ledyFeeCheckin);

                    if (list.size() > 0) {
                        Cell cell = row.getCell(13);
                        String buyOrg = cell.getStringCellValue();
                        AtomicBoolean isExit = new AtomicBoolean(true);
                        list.forEach(item -> {
                            if (buyOrg.equals(item.getPayers())) {
                                isExit.set(false);
                            }
                        });
                        if (isExit.get()) {
                            remark.setCellValue(remark.getStringCellValue() + buyOrg);
                            cell.setCellValue(list.get(0).getPayers()); // 修改数据
                        }
                    }
                }

            }
            // 保存修改后的Excel文件
//            new FileInputStream()
            FileOutputStream fos = new FileOutputStream("data_modified.xlsx");
            workbook.write(fos);

            // 关闭文件流
//            fis.close();
            fos.close();
            IOUtils.closeQuietly(workbook);
            System.out.println("Excel修改完成！");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return success();
    }

    @PostMapping("/importTemplate")
    public void importTemplate(HttpServletResponse response) {
        try {

            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            // 保存修改后的Excel文件
            FileInputStream fis = new FileInputStream("data_modified.xlsx");
            OutputStream fos = response.getOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            while ((length = fis.read(buffer)) > 0) {
                fos.write(buffer, 0, length);
            }

            // 关闭文件流
//            fis.close();
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 导出收费管理列表
     */
    @PreAuthorize("@ss.hasPermi('erp:checkin:export')")
    @Log(title = "收费管理", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, LedyFeeCheckin ledyFeeCheckin) {
        List<LedyFeeCheckin> list = ledyFeeCheckinService.selectLedyFeeCheckinList(ledyFeeCheckin);
        ExcelUtil<LedyFeeCheckin> util = new ExcelUtil<LedyFeeCheckin>(LedyFeeCheckin.class);
        util.exportExcel(response, list, "收费管理数据");
    }

    /**
     * 获取收费管理详细信息
     */
    @PreAuthorize("@ss.hasPermi('erp:checkin:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return success(ledyFeeCheckinService.selectLedyFeeCheckinById(id));
    }

    /**
     * 新增收费管理
     */
    @PreAuthorize("@ss.hasPermi('erp:checkin:add')")
    @Log(title = "收费管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody LedyFeeCheckin ledyFeeCheckin) {
        return toAjax(ledyFeeCheckinService.insertLedyFeeCheckin(ledyFeeCheckin));
    }

    /**
     * 修改收费管理
     */
    @PreAuthorize("@ss.hasPermi('erp:checkin:edit')")
    @Log(title = "收费管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody LedyFeeCheckin ledyFeeCheckin) {
        return toAjax(ledyFeeCheckinService.updateLedyFeeCheckin(ledyFeeCheckin));
    }

    /**
     * 删除收费管理
     */
    @PreAuthorize("@ss.hasPermi('erp:checkin:remove')")
    @Log(title = "收费管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(ledyFeeCheckinService.deleteLedyFeeCheckinByIds(ids));
    }
}
